#!/bin/bash
#GPL
#set -x
BPILICENSE="GPLv2 or any later version"
BPICMD="bpi-hw"
BPICMDVERSION="v1.3.3(github)"
BPIOPT="$*"

CONFFILE=""
BPIDIR="/var/lib/bananapi"
BPIHWFILE="$BPIDIR/board.sh"
NEWBOARD=""
F_CHANGE="no"
MODEL=""
NEWMODEL=

ID="Banana Pi M3"
BOARD="bpi-m3"
F_BTCMD="none"
F_AUTO="no"
F_OSDEP="no"
F_BOARD="no"
F_TEMP="no"

HAVE_BT="no"

if [[ $DEVICE == "" ]]; then DEVICE="/dev/mmcblk1"; fi
#
# BPIFILE / BPIURL
#
BPIFILE="$HOME/.${BPICMD}.lst"
#BPI-ROOT.lst
#
## Hello from Google,
## On Aug 31, 2016, we will discontinue serving content via 
## googledrive.com/host/[id] and the webpages will not be accessible anymore.
#
#BPIURL="https://googledrive.com/host/0B_YnvHgh2rwjVE10U3U0Q0NCdWM"
BPIURL="https://github.com/BPI-SINOVOIP/BPI-files/raw/master/others/for-bpi-tools/BPI-ROOT.lst"
BPIURLNEW=""
#
## URLBASE
#
URLBASE="https://github.com/BPI-SINOVOIP/BPI-files/raw/master"
#
## URLCONF
#
URLCONF="${URLBASE}/others/for-bpi-tools/conf"
#
# update / download
#

######################################################
for IN in "$@"
do
  if [[ "$IN" == *"="* ]] ; then
    P=${IN%%=*}
    V=${IN##*=}
    echo "INFO: $P=${V:-(empty)}"
    eval $P=$V
  fi
done
######################################################

usage() {
cat - >&2 <<EOF
${BPICMD}(${BPICMDVERSION}), bananapi hardware tools.

Usage: bpi-hw [OPTIONS]...
       bpi-hw [ --help | -v | --version ]

Options:

  -A, --auto            auto detect board
  -B, --board BOARD     set BOARD=[bpi-m3|bpi-m2p|bpi-m2|bpi-r1|bpi-m1p|bpi-m1]
  -b, --bt CMD          BT function, CMD=[on|status|scan|list|unblock]
                        or  CMD=[rfkill|hciconfig|hcitool|bluetoothctl]
  -O, --osdep MODE      OS DEP. setup, MODE=[yes|list|backup|restore]
  -t, --temp            Print temp.
  -c, --config          config file
  -h, --help            Print usage
  -v, --version         Print version information and quit

EOF
  exit 1
}

F_INDEX=
download_index() {
  if [ "x${F_INDEX}" == "xOK" ] ; then
    return
  fi
  echo BPIFILE=$BPIFILE
  echo "Wait for download index file ..."
  curl -s -L $BPIURL > $BPIFILE
  echo "OK!!\n"
  F_INDEX=OK
}

get_conffile() {
  CONFDIRS=". board os tools pkg"
  FILE=$1
  if [ ! -f "${FILE}" ] ; then
    echo "Wait for download $FILE ..."
    for IN in ${CONFDIRS} ; do
      U="${URLCONF}/${IN}/${FILE}"
      curl -s -L $U > $FILE
      eval `grep "^BPICONF" $FILE`
      if [ "x$FILE" == "x$BPICONF" ] ; then
        echo $U
        echo "OK!!\n"
        break 
      fi
    done
  fi
}

get_bpi_github() {
  FILE=$1
  DIRS=". SD/BPI-ROOT SD/BPI-BOOT SD/100MB rootfs"
  if [ ! -f "${FILE}" ] ; then
    echo "Wait for download $FILE ..."
    for D in ${DIRS} ; do
      echo -n "."
      U="${URLBASE}/${D}/${FILE}"
      #echo $U
      curl -s -L $U > $FILE
      SHELLCMD=$?
      if [ ! $SHELLCMD -eq 0 ] ; then
        rm -f $FILE
        continue
      fi
      #check file
      ERRORMSG=("error" "Not Found")
      for CHECK in "${ERRORMSG[@]}" ; do
        if [ ! -f "${FILE}" ] ; then
           break
        fi
        #echo "grep ${CHECK} $FILE "
        grep "${CHECK}" $FILE 2>&1 >/dev/null
        SHELLCMD=$?
        if [ $SHELLCMD -eq 0 ] ; then
          rm -f $FILE
        fi
      done
      if [ -f "${FILE}" ] ; then
        echo $U
        echo "OK!!\n"
        break
      fi
    done
  fi
}

list_files() {
  echo
  echo "bpi files:"
  awk '{ printf "%-12s\t%s\n", $2, $4 }' $BPIFILE
}

get_all_versions() {
  echo
  echo "bpi files:"
  for IN in `cat $BPIFILE | awk '{ print $2 }'` ; do
    IMGFILE=/usr/bin/$IN
    BPICMDVERSION="old version"
  if [ -f "${IMGFILE}" ] ; then
    eval `grep "^BPICMDVERSION" $IMGFILE`
  else
    BPICMDVERSION="NOT INSTALLED"
  fi
  echo "$IMGFILE	$BPICMDVERSION"
  done
}

get_all_files() {
  echo
  echo "download bpi files:"
  for IN in `cat $BPIFILE | awk '{ print $2 }'` ; do
    echo $IN
    IMGFILE=$IN
    get_bpifile
    chmod 644 $IMGFILE
  done
}

upgrade_all_files() {
  echo
  echo "upgrade bpi files:"
  for IN in `cat $BPIFILE | awk '{ print $2 }'` ; do
    IMGFILE=/usr/bin/$IN
    echo $IMGFILE
    if [ -f "${IN}" ] ; then
      cp -a ${IN} ${IMGFILE}
      chown root:root ${IMGFILE}
      chmod 755 ${IMGFILE}
    fi
  done
}

get_bpifile() {
  MD5TMP="/tmp/.md5.tmp.$$"
  #echo "BPIFILE=$BPIFILE"
  #echo "IMGFILE=$IMGFILE"
  #echo "MD5TMP=$MD5TMP"
  LINE=`cat $BPIFILE | grep $IMGFILE`
  #echo LINE=$LINE
  set -- $LINE
  BPIURL=$3
  if [ ! -z ${BPIURLNEW} ] ; then
    BPIURL=${BPIURLNEW}/$2
  fi
  echo "$1  $2" > $MD5TMP
  if [ ! -f "${IMGFILE}" ] ; then
    curl -s -L $BPIURL > $IMGFILE
  fi
  md5sum -c $MD5TMP
  rm -f $MD5TMP
  file $IMGFILE | grep "shell script" >/dev/null
  SHELLCMD=$?
  if [ $SHELLCMD -eq 0 ] ; then
    eval `grep "^BPICMDVERSION" $IMGFILE`
    echo "$IMGFILE: $BPICMDVERSION"
  fi
}

requires_root() {
  if [ "$(id -u)" -ne 0 ]; then
    echo >&1 "ERROR: This command can only be used by root."
    exit 1
  fi
}

bpi_check_model() {
  # check device-tree
  if [ ! -f /proc/device-tree/model ] ; then
    MODEL=
    NEWMODEL=
    return
  fi
  MODEL=$(cat /proc/device-tree/model)
  echo MODEL=$MODEL
  case $MODEL in
    *SC7021*)
      NEWMODEL="bpi-f2s"
      return
      ;;
    *BPI-M4*|*RTD1395*|*Lion*)
      NEWMODEL="bpi-m4"
      return
      ;;
    *BPI-W2*|*RTD1296*)
      NEWMODEL="bpi-w2"
      return
      ;;
    *BPI-R2*)
      NEWMODEL="bpi-r2"
      return
      ;;
    *Lamobo\ R1*)
      NEWMODEL="bpi-r1"
      return
      ;;
    *BPI-M3*)
      NEWMODEL="bpi-m3"
      return
      ;;
    *BPI-M2-Zero*)
      NEWMODEL="bpi-m2z"
      return
      ;;
    *BPI-M1-Plus*)
      NEWMODEL="bpi-m1p"
      return
      ;;
    *BPI-M2+*H5*)
      NEWMODEL="bpi-m2p-h5"
      return
      ;;
    *BPI-M2-Plus*)
      NEWMODEL="bpi-m2p"
      return
      ;;
    *BPI-M2-Ultra*|*M2\ Berry*)
      NEWMODEL="bpi-m2u"
      return
      ;;
    *M2\ Magic*)
      NEWMODEL="bpi-m2m"
      return
      ;;
    *LeMaker*)
      NEWMODEL="bpi-m1"
      return
      ;;
    *BananaPi-M64*)
      NEWMODEL="bpi-m64"
      return
      ;;
    *Banana*)
      NEWMODEL="bpi-m1"
      return
      ;;
  esac
}

bpi_check_auto() {
  NEWBOARD="bpi-m3"
  # parse command line arguments
  for arg in $(cat /proc/cmdline); do
    case $arg in
      board=*)
        NEWBOARD="${arg#*=}"
        return
        ;;
    esac
  done
  #BPI
  bpi_check_model
  if [ ! -z ${NEWMODEL} ] ; then
    NEWBOARD=${NEWMODEL}
    return
  fi
  # x86
  if (( $(uname -p | grep -ci -m1 'x86') == 1 )); then
    NEWBOARD="bpi-x86"
    return
  fi
  # rpi
  if (( $(cat /proc/cpuinfo | grep -ci -m1 'bcm') == 1 )); then
    NEWBOARD="bpi-rpi"
    return
  fi
  # new , non-sunxi
  if (( $(cat /proc/cpuinfo | grep -ci -m1 'sun') != 1 )); then
    NEWBOARD="bpi-new"
    return
  fi
  # sun8i , bpi-m3 or bpi-m2p
  if (( $(cat /proc/cpuinfo | grep -ci -m1 'sun8i') == 1 )); then
    # sun8i , bpi-m3 8 cores or bpi-m2p 4 cores
    if (( $(cat /proc/cpuinfo | grep processor | wc -l ) == 8 )); then
      NEWBOARD="bpi-m3"
    else
      NEWBOARD="bpi-m2p"
    fi
    return
  fi
  # sun50i , bpi-m64
  if (( $(cat /proc/cpuinfo | grep -ci -m1 'sun50i') == 1 )); then
    NEWBOARD="bpi-m64"
    return
  fi
  # sun6i , bpi-m2
  if (( $(cat /proc/cpuinfo | grep -ci -m1 'sun6i') == 1 )); then
    NEWBOARD="bpi-m2"
    return
  fi
  # sun7i , bpi-m1 / bpi-m1p / bpi-r1
  if (( $(cat /proc/cpuinfo | grep -ci -m1 'sun7i') == 1 )); then
    CHIP="a20"
    DMESGFILE="/tmp/.${BPICMD}.tmp.$$"
    dmesg -t >$DMESGFILE
    # sun7i , bpi-r1 with SWICTH BCM53125
    if (( $(cat $DMESGFILE | grep -ci -m1 'BCM53125') == 1 )); then
      NEWBOARD="bpi-r1"
    else
      # sun7i , bpi-m1p 40 pins with I2S / bpi-m1 26 pins
      if (( $(cat $DMESGFILE | grep -ci -m1 'sunxi-sndi2s') == 1 )); then
        NEWBOARD="bpi-m1p"
      else
        NEWBOARD="bpi-m1"
      fi
    fi
    rm -f $DMESGFILE
    return
  fi
}

bpi_turn_on_bt() {
  requires_root
  echo "info: try to bpi_turn_on_bt"
  if [ -f /usr/local/bin/bpi-bt-patch ] ; then
    . /usr/local/bin/bpi-bt-patch
  fi
  if [ -f /usr/local/bin/bpi-bt-on ] ; then
    . /usr/local/bin/bpi-bt-on
  fi
}

bpi_hw_bt() {
  CMD=$1
  case ${CMD} in
  none)
    ;;
  off)
    ;;
  on)
    if [ "x$HAVE_BT" == "xyes" ] ; then
      bpi_turn_on_bt
    fi
    ;;
  status)
    echo "hcitool dev"
    hcitool dev
    ;;
  scan)
    echo "hcitool scan"
    hcitool scan
    ;;
  list)
    echo "rfkill list"
    rfkill list
    ;;
  unblock)
    echo "rfkill unblock bluetooth"
    rfkill unblock bluetooth
    ;;
  rfkill)
    echo "rfkill $BPIOPT"
    rfkill $BPIOPT
    ;;
  hciconfig)
    echo "hciconfig $BPIOPT"
    hciconfig $BPIOPT
    ;;
  hcitool)
    echo "hcitool $BPIOPT"
    hcitool $BPIOPT
    ;;
  bluetoothctl)
    echo "bluetoothctl $BPIOPT"
    bluetoothctl $BPIOPT
    ;;
  *)
    echo "CMD=$CMD unsupport!!"
    echo "CMD=[on|status|scan|list|unblock|rfkill|hciconfig|hcitool|bluetoothctl]"
    ;;
  esac
}

bpi_hw_osdep() {
  OSDEPFILE="$BPIDIR/osdep.sh"
  if [ -f $OSDEPFILE ] ; then
    . $OSDEPFILE
  else
    BPI_OS="xenial_mate"
    echo "BPI_OS=$BPI_OS" > $OSDEPFILE 
  fi
  BPI_OSDIR="$BPIDIR/run/$BPI_OS/$BOARD"
  if [ ! -d $BPI_OSDIR ] ; then
    sudo mkdir -p $BPI_OSDIR
  fi
  HWDEPFILE="$BPIDIR/osdep/${BPI_OS}.conf"
  BAKFILE="$BPI_OSDIR/backup.tgz"
  HWDEP=$(cat $HWDEPFILE)
  MODE=$1
  #
  echo BPI_OS=$BPI_OS
  echo OSDEPFILE=$OSDEPFILE
  echo BPI_OSDIR=$BPI_OSDIR
  echo HWDEPFILE=$HWDEPFILE
  echo BAKFILE=$BAKFILE
  #
  requires_root
  case ${F_OSDEP} in
  list)
    echo "HW osdep files:"
    for IN in $HWDEP ; do
      echo $IN
    done
    ;;
  backup)
    echo "HW osdep files(backup to $BAKFILE):"
    tar czvf $BAKFILE -C / -T $HWDEPFILE
    ;;
  restore)
    echo "HW osdep files(restore from $BAKFILE):"
    tar xvf $BAKFILE -C /
    ;;
  yes)
    echo $BOARD
    BAKFILE="$BPI_OSDIR/bananapi.tgz"
    echo "HW osdep files(backup to $BAKFILE):"
    tar czf $BAKFILE -C / -T $HWDEPFILE
    for IN in $HWDEP ; do
      rm -rf $IN
    done
    echo "HW osdep files(new from $BOARD):"
    (cd $BPI_OSDIR/root ; tar cf - . ) | (cd / ; tar xvf -)
    ldconfig
    ;;
  *)
    echo $BOARD
    #ldconfig
    ;;
  esac
}

bpi_hw_main() {
  if [ ! -d $BPIDIR ] ; then
    if [ "$(id -u)" -ne 0 ]; then
      echo "INFO: first time, please run sudo $BPICMD"
      exit 1
    fi
    requires_root
    mkdir -p $BPIDIR
  fi
  #
  ## detect board
  #
  if [ -f $BPIHWFILE ] ; then
    . $BPIHWFILE
  else
    F_AUTO="yes"
    F_CHANGE="yes"
  fi
  if [ "x$F_AUTO" == "xyes" ] ; then
    bpi_check_auto
    if [ "x$NEWBOARD" != "x$BOARD" ] ; then
      F_CHANGE="yes"
    fi
    if [ "x$F_CHANGE" == "xyes" ] ; then
      requires_root
      echo "BOARD=$NEWBOARD" > $BPIHWFILE
      echo "BOARD_AUTO=$NEWBOARD" >> $BPIHWFILE
      echo "BOARD_OLD=$BOARD" >> $BPIHWFILE
      BOARD=$NEWBOARD
    fi
  fi
  if [ "x$F_BOARD" == "xyes" ] ; then
    requires_root
    echo "#DATE=$(date)" >> $BPIHWFILE
    echo "BOARD_SET=${SET_BOARD}" >> $BPIHWFILE
    BOARD=${SET_BOARD}
    echo "BOARD=$BOARD" >> $BPIHWFILE
  fi
  echo $BOARD
  BOARDDIR=$BPIDIR/board
  BOARDFILE=$BOARDDIR/$BOARD
  if [ ! -d $BOARDDIR ] ; then
    sudo mkdir -p $BOARDDIR
  fi
  if [ ! -f $BOARDFILE ] ; then
     requires_root
     echo "HAVE_VER=1" >> $BOARDFILE
     echo "HAVE_GMAC=yes" >> $BOARDFILE
     echo "HAVE_SATA=no" >> $BOARDFILE
     echo "HAVE_LCD=no" >> $BOARDFILE
     echo "HAVE_MIPILCD=no" >> $BOARDFILE
     echo "HAVE_CAMERA=no" >> $BOARDFILE
     echo "HAVE_BT=no" >> $BOARDFILE
     echo "HAVE_WIFI=no" >> $BOARDFILE
     echo "HAVE_SWITCH=no" >> $BOARDFILE
  fi
  . $BOARDFILE
  #
  ## turn on BT
  #
  if [ "x$F_BTCMD" != "xnone" ] ; then
    bpi_hw_bt $F_BTCMD
  fi

  #
  ## config files
  #
  if [ "x$F_OSDEP" != "xno" ] ; then
    bpi_hw_osdep $F_OSDEP
  fi
  #
  ## check temp
  #
  if [ "x$F_TEMP" == "xyes" ] ; then
    TEMPFILE=/sys/class/thermal/thermal_zone0/temp
    if [ -f $TEMPFILE ] ; then
      cat $TEMPFILE
    fi
  fi
}

#step 0: main/getopt
BPICMDOPT="c:B:AO:b:tvh"

GETOPTEST=`getopt --version`
case $GETOPTEST in
getopt*) # GNU getopt
  BPI_TEMP=`getopt -l config: -l board: -l auto -l osdep: -l bt: -l temp -l version -l help -- +${BPICMDOPT} "$@"`
  ;;
*) # POSIX getopt ?
  BPI_TEMP=`getopt ${BPICMDOPT} "$@"`
  ;;
esac

if test "$?" -ne 0; then
  usage
fi

eval set -- "$BPI_TEMP"

BPIDOPTS=""

while test "X$1" != "X--"; do
  case "$1" in
    -c|--config)
       shift
       CONFFILE="$1"
       echo "CONFFILE=${CONFFILE}"
       #
       ## run config file
       #
       get_conffile ${CONFFILE}
       if [ -f "${CONFFILE}" ] ; then
         . ${CONFFILE}
       fi
       #
       ;;
    -B|--board)
       shift
       F_BOARD="yes"
       SET_BOARD="$1"
       echo "SET_BOARD=${SET_BOARD}"
       ;;
    -A|--auto)
       F_AUTO="yes"
       echo "F_AUTO=${F_AUTO}"
       ;;
    -O|--osdep)
       shift
       F_OSDEP="$1"
       echo "F_OSDEP=${F_OSDEP}"
       ;;
    -b|--bt)
       shift
       F_BTCMD="$1"
       echo "F_BTCMD=${F_BTCMD}"
       ;;
    -t|--temp)
       F_TEMP="yes"
       echo "F_TEMP=${F_TEMP}"
       ;;
    -v|--version)
       usage
       exit 0
       ;;
    -h|--help)
       usage
       ;;
  esac
  shift
done

shift #get rid of the '--'
BPIOPT=$*
#echo BPTOPT=$BPIOPT


#step 1: main
bpi_hw_main

